/**
  ******************************************************************************
  * @file    queue.c
  * @author  N-K-J
  * @version V0.0.1
  * @date    2012/12/11
  * @brief   queue.c
  ******************************************************************************
 **/

#include "queue.h"

#if QUEUECB

typedef struct _queuecb
{
    void *header;       //队列缓冲区首地址
    uint8_t dataWidth;  //队列位宽,8,16,32
    uint32_t length;    //队列长度
    uint32_t rindex;    //读索引
    uint32_t windex;    //写索引
    uint32_t count;     //已存长度
}QueueCB,*pQueueCB;


static volatile QueueCB queuecb[MAXQNUM];

/* 队列初始化
 * 函数名：void qInit(void)
 * 输入：
 * 返回：
*/
void qInit(void)
{
    uint32_t i = 0;
    for(i = 0;i < (sizeof(QueueCB) * MAXQNUM);i ++)
    {
        ((uint8_t *)queuecb)[i] = 0;
    }
}

/* 创建一个队列
 * 函数名：eQerrorcode qCreate(void *header,uint8_t width,uint32_t len)
 * 输入：
 *     header  队列缓冲区首地址
 *     width   队列位宽
 *     len     队列长度
 * 返回：见队列代码
 */
eQerrorcode qCreate(void *header,uint8_t width,uint32_t len)
{
    uint32_t i = 0;
    for(i = 0;i < MAXQNUM;i ++)
    {
        if(queuecb[i].header == 0)
        {
            queuecb[i].header = header;
            queuecb[i].dataWidth = width;
            queuecb[i].length = len;
            queuecb[i].rindex = 0;
            queuecb[i].windex = 0;
            queuecb[i].count = 0;

            return Q_SUCCESS;
        }
    }
    return Q_FAIL;
}

/* 删除一个队列
 * 函数名：eQerrorcode qDelete(void *header)
 * 输入：
 *     header  队列缓冲区首地址
 * 返回：见队列代码
 */
eQerrorcode qDelete(void *header)
{
    uint32_t i = 0;
    for(i = 0;i < MAXQNUM;i ++)
    {
        if(queuecb[i].header == header)
        {
            queuecb[i].header = 0;
            queuecb[i].dataWidth = 0;
            queuecb[i].length = 0;
            queuecb[i].rindex = 0;
            queuecb[i].windex = 0;
            queuecb[i].count = 0;

            return Q_SUCCESS;
        }
    }
    return Q_FAIL;
}

/* 队列状态
 * 函数名：eQerrorcode qStatus(void *header)
 * 输入：
 *     header  队列缓冲区首地址
 * 返回：见队列代码
 */ 
eQerrorcode qStatus(void *header)
{
    uint32_t i = 0;
    for(i = 0;i < MAXQNUM;i ++)
    {
        if(queuecb[i].header == header)
        {
            if(queuecb[i].count == 0)
                return Q_EMPTY;
            else if(queuecb[i].count == queuecb[i].length)
                return Q_FULL;
            else if((0 < queuecb[i].count) && (queuecb[i].count < queuecb[i].length))
                return Q_HALF;
            else
                return Q_FAIL;
        }
    }
    return Q_FAIL;
}

/* 获取队列已存入的数据个数
 * 函数名：eQerrorcode qCount(void *header,uint32_t *len)
 * 输入：
 *     header  队列缓冲区首地址
 *     len     已存入的数据个数
 * 返回：见队列代码
 */ 
eQerrorcode qCount(void *header,uint32_t *len)
{
    uint32_t i = 0;
    for(i = 0;i < MAXQNUM;i ++)
    {
        if(queuecb[i].header == header)
        {
            *len = queuecb[i].count;

            return Q_SUCCESS;
        }
    }
    return Q_FAIL;
}

/* 往一个队列添加一个元素
 * 函数名：eQerrorcode qAddItem(void *header,uint32_t data)
 * 输入：
 *     header  队列缓冲区首地址
 *     data    要存入的数据
 * 返回：见队列代码
 */ 
eQerrorcode qAddItem(void *header,uint32_t data)
{
    uint32_t i = 0;
    for(i = 0;i < MAXQNUM;i ++)
    {
        if(queuecb[i].header == header)
        {
            if((0 <= queuecb[i].count) && (queuecb[i].count < queuecb[i].length))
            {
                switch(queuecb[i].dataWidth/8)            
                {
                    case 1:
                        ((uint8_t *)queuecb[i].header)[queuecb[i].windex] = data;                
                        queuecb[i].windex = ((queuecb[i].windex + 1) % queuecb[i].length);
                        queuecb[i].count ++;
                        return Q_SUCCESS;
                    break;

                    case 2:
                        ((uint16_t *)queuecb[i].header)[queuecb[i].windex] = data;                
                        queuecb[i].windex = ((queuecb[i].windex + 1) % queuecb[i].length);
                        queuecb[i].count ++;
                        return Q_SUCCESS;
                    break;

                    case 4:
                        ((uint32_t *)queuecb[i].header)[queuecb[i].windex] = data;                
                        queuecb[i].windex = ((queuecb[i].windex + 1) % queuecb[i].length);
                        queuecb[i].count ++;
                        return Q_SUCCESS;
                    break;

                    default:
                        return Q_FAIL;
                    break;
                }
            }
            else if(queuecb[i].length == queuecb[i].count)
                return Q_FULL;
            else
                return Q_FAIL;
        }
    }
    return Q_FAIL;
}

/* 从一个队列取出一个元素
 * 函数名：eQerrorcode qOutItem(void *header,uint32_t *data)
 * 输入：
 *     header  队列缓冲区首地址
 *     data    接收地址,该数据必须是32位类型
 * 返回：见队列代码
 */
eQerrorcode qOutItem(void *header,uint32_t *data)
{
    uint32_t i = 0;
    for(i = 0;i < MAXQNUM;i ++)
    {
        if(queuecb[i].header == header)
        {
            if((0 < queuecb[i].count) && (queuecb[i].count <= queuecb[i].length))
            {
                switch(queuecb[i].dataWidth/8)            
                {
                    case 1:
                        *data = ((uint8_t *)queuecb[i].header)[queuecb[i].rindex];                
                        queuecb[i].rindex = ((queuecb[i].rindex + 1) % queuecb[i].length);
                        queuecb[i].count --;
                        return Q_SUCCESS;
                    break;

                    case 2:
                        *data = ((uint16_t *)queuecb[i].header)[queuecb[i].rindex];                
                        queuecb[i].rindex = ((queuecb[i].rindex + 1) % queuecb[i].length);
                        queuecb[i].count --;
                        return Q_SUCCESS;
                    break;

                    case 4:
                        *data = ((uint32_t *)queuecb[i].header)[queuecb[i].rindex];                
                        queuecb[i].rindex = ((queuecb[i].rindex + 1) % queuecb[i].length);
                        queuecb[i].count --;
                        return Q_SUCCESS;
                    break;

                    default:
                        return Q_FAIL;
                    break;
                }
            }
            else if(0 == queuecb[i].count)
                return Q_EMPTY;
            else
                return Q_FAIL;
        }
    }
    return Q_FAIL;
}

/* 清空一个队列
 * 函数名：eQerrorcode qFlush(void *header)
 * 输入：
 *     header  队列缓冲区首地址
 * 返回：见队列代码
 */ 
eQerrorcode qFlush(void *header)
{
    uint32_t i = 0;
    for(i = 0;i < MAXQNUM;i ++)
    {
        if(queuecb[i].header == header)
        {
            queuecb[i].rindex = 0;
            queuecb[i].windex = 0;
            queuecb[i].count = 0;
            return Q_SUCCESS;
        }
    }
    return Q_FAIL;
}


#endif

